package com.kgcx.common.utils;

import com.alibaba.fastjson.util.TypeUtils;
import com.kgcx.common.annotation.securety.Sensitive;
import com.xiaoleilu.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;

@Slf4j
public class SensitiveUtils {
    public static String getEncrypt(Object o, Class domain, String fieldName) {
        if (null != o && null != domain && null != fieldName) {
            String oStr = o.toString();
            if (StringUtils.isNotBlank(oStr)) {
                Field field = ReflectHelper.getTargetField(domain, fieldName);
                if (null != field) {
                    if (field.isAnnotationPresent(Sensitive.class)) {
                        Sensitive sensitive = field.getAnnotation(Sensitive.class);
                        //加密后再传入业务层
                        return SecureUtil.aes(sensitive.key()).encryptHex(oStr);
                    }
                }
            }
        }
        return TypeUtils.castToString(o);
    }

    public static String getDecrypt(Object o, Class domain, String fieldName) {
        if (null != o && null != domain && null != fieldName) {
            Field field = ReflectHelper.getTargetField(domain, fieldName);
            if (null != field) {
                if (field.isAnnotationPresent(Sensitive.class)) {
                    Sensitive sensitive = field.getAnnotation(Sensitive.class);
                    if (sensitive.isEncrypt()) {
                        try {
                            //是否需要解密
                            return SecureUtil.aes(sensitive.key()).decryptStr(o.toString());
                        } catch (Exception e) {
                            log.warn("敏感字段解密异常，可能是历史数据，并未加密存储，将采用原文输出.字段名：" + field.getName());
                        }
                    }
                }
            }
        }
        return TypeUtils.castToString(o);
    }

    public static void encryptObject(Object obj) {
        if (null != obj) {
            Field[] declaredFields = obj.getClass().getDeclaredFields();
            if (ArrayUtils.isNotEmpty(declaredFields)) {
                for (Field declaredField : declaredFields) {
                    encryptField(obj, declaredField);
                }
            }
        }
    }

    public static void encryptField(Object obj, Field declaredField) {
        if (null != declaredField) {
            Object fieldValue = ReflectHelper.getFieldValue(obj, declaredField.getName());
            if (null != fieldValue && StringUtils.isNotBlank(fieldValue.toString())) {
                if (declaredField.isAnnotationPresent(Sensitive.class)) {
                    Sensitive sensitive = declaredField.getAnnotation(Sensitive.class);
                    if (sensitive.isEncrypt()) {
                        //加密后再传入业务层
                        String encryptValue = SecureUtil.aes(sensitive.key()).encryptHex(fieldValue.toString());
                        ReflectHelper.setFieldValue(obj, declaredField.getName(), encryptValue);
                    }
                }
            }
        }
    }

    public static void decryptObject(Object obj) {
        Field[] declaredFields = obj.getClass().getDeclaredFields();
        if (ArrayUtils.isNotEmpty(declaredFields)) {
            for (Field declaredField : declaredFields) {
                Object fieldValueObj = ReflectHelper.getFieldValue(obj, declaredField.getName());
                if (null != fieldValueObj && StringUtils.isNotBlank(fieldValueObj.toString())) {
                    if (declaredField.isAnnotationPresent(Sensitive.class)) {
                        Sensitive sensitive = declaredField.getAnnotation(Sensitive.class);
                        String fieldValue = fieldValueObj.toString();
                        if (sensitive.isEncrypt()) {
                            try {
                                //是否需要解密
                                fieldValue = SecureUtil.aes(sensitive.key()).decryptStr(fieldValue);
                            } catch (Exception e) {
                                log.warn("敏感字段解密异常，可能是历史数据，并未加密存储，将采用原文输出.字段名：" + declaredField.getName());
                            }
                        }
                        ReflectHelper.setFieldValue(obj, declaredField.getName(), fieldValue);
                    }
                }
            }
        }
    }

    public static void hideObject(Object obj) {
        Field[] declaredFields = obj.getClass().getDeclaredFields();
        if (ArrayUtils.isNotEmpty(declaredFields)) {
            for (Field declaredField : declaredFields) {
                Object fieldValueObj = ReflectHelper.getFieldValue(obj, declaredField.getName());
                if (null != fieldValueObj && StringUtils.isNotBlank(fieldValueObj.toString())) {
                    if (declaredField.isAnnotationPresent(Sensitive.class)) {
                        Sensitive sensitive = declaredField.getAnnotation(Sensitive.class);
                        String fieldValue = fieldValueObj.toString();
                        if (sensitive.hide()) {
                            //是否需要隐藏
                            int hideEndIndex = sensitive.hideEndIndex();
                            if (hideEndIndex == -1) {
                                //一直隐藏到最末字符
                                hideEndIndex = fieldValue.length();
                            }
                            //把需要隐藏的字符替换，默认替换为隐藏字符（默认为*）
                            String repalceStr = StringUtils.substring(fieldValue, sensitive.hideStartIndex(), hideEndIndex);
                            fieldValue = StringUtils.replace(fieldValue
                                    , repalceStr
                                    , StringUtils.repeat(sensitive.hideWord(), repalceStr.length()));
                            ReflectHelper.setFieldValue(obj, declaredField.getName(), fieldValue);
                        }
                    }
                }
            }
        }
    }

}
